package com.ruoyi.web.controller.info;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.info.domain.VinfoCompany;
import com.ruoyi.info.domain.VinfoCountOrder;
import com.ruoyi.info.domain.vo.CarLocationVo;
import com.ruoyi.info.domain.vo.VinfoCountDaily;
import com.ruoyi.info.domain.vo.VinfoCountMonth;
import com.ruoyi.info.domain.vo.VinfoCountOrderVo;
import com.ruoyi.info.service.IVinfoCountOrderService;
import com.ruoyi.web.controller.util.*;
import com.ruoyi.wx.service.IVehiclesLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.info.domain.VinfoCar;
import com.ruoyi.info.service.IVinfoCarService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;

/**
 * 车辆信息Controller
 *
 * @author oy
 * @date 2022-12-16
 */
@RestController
@RequestMapping("/info/car")
public class VinfoCarController extends BaseController {
    @Resource
    private IVinfoCarService infoCarService;

    private final CarUtil carUtil = new CarUtil();

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private IVinfoCountOrderService vinfoCountOrderService;

    /**
     * 查询车辆信息列表
     */
    @PreAuthorize("@ss.hasPermi('info:car:list')")
    @GetMapping("/list")
    public TableDataInfo list(VinfoCar vinfoCar) {
        startPage();
        long userId = SecurityUtils.getUserId();
        List<VinfoCar> list = infoCarService.selectVinfoCarList(vinfoCar,userId);
        return getDataTable(list);
    }

    /**
     * 导出车辆信息列表
     */
    @PreAuthorize("@ss.hasPermi('info:car:export')")
    @Log(title = "车辆信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, VinfoCar vinfoCar) {
        long userId = SecurityUtils.getUserId();
        List<VinfoCar> list = infoCarService.selectVinfoCarList(vinfoCar,userId);
        ExcelUtil<VinfoCar> util = new ExcelUtil<>(VinfoCar.class);
        util.exportExcel(response, list, "车辆信息数据");
    }

    /**
     * 获取车辆信息详细信息
     */
    @PreAuthorize("@ss.hasPermi('info:car:query')")
    @GetMapping(value = "/{carId}")
    public AjaxResult getInfo(@PathVariable("carId") Long carId) {
        return success(infoCarService.selectVinfoCarByCarId(carId));
    }

    /**
     * 新增车辆信息
     */
    @PreAuthorize("@ss.hasPermi('info:car:add')")
    @Log(title = "车辆信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody VinfoCar vinfoCar) {
        return toAjax(infoCarService.insertVinfoCar(vinfoCar));
    }

    /**
     * 修改车辆信息
     */
    @PreAuthorize("@ss.hasPermi('info:car:edit')")
    @Log(title = "车辆信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody VinfoCar vinfoCar) {
        return toAjax(infoCarService.updateVinfoCar(vinfoCar));
    }

    /**
     * 删除车辆信息
     */
    @PreAuthorize("@ss.hasPermi('info:car:remove')")
    @Log(title = "车辆信息", businessType = BusinessType.UPDATE)
    @PutMapping("/{carIds}")
    public AjaxResult remove(@PathVariable Long[] carIds) {
        return toAjax(infoCarService.deleteVinfoCarByCarIds(carIds));
    }

    /**
     * 获取设备id列表
     */
    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @GetMapping("deviceidlist")
    public AjaxResult selectDeviceIds() {
        List<String> ids = infoCarService.selectDeviceNos();
        return AjaxResult.success(ids);
    }

    /**
     * 获取所有车辆位置信息
     */
    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @GetMapping("/alllocations")
    public AjaxResult selectAllCarLocations() {
        long userId = SecurityUtils.getUserId();
        List<CarLocationVo> carLocationVoList = infoCarService.selectAllCarLocations(userId);
        return AjaxResult.success(carUtil.handleLocations(carLocationVoList));
    }

    /**
     * 获取车辆位置信息
     */
    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @GetMapping("/locations")
    public AjaxResult selectCarLocations(List<Long> carIdlist) {
        long userId = SecurityUtils.getUserId();
        List<CarLocationVo> carLocationVoList = infoCarService.selectCarLocations(carIdlist);
        return AjaxResult.success(carUtil.handleLocations(carLocationVoList));
    }

    /**
     * 根据车牌号获取位置信息
     */
    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @GetMapping("/location")
    public AjaxResult selectCarLocationByCarId(String deviceNo){
        List<CarLocationVo> carLocationVoList = infoCarService.selectCarLocationByDeviceNo(deviceNo);
        return AjaxResult.success(((ArrayList<CarLocationVo>)carUtil.handleLocations(carLocationVoList).get("carLocationVoList")).get(0));
    }

    /**
     * 查询车辆轨迹信息
     */
    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @PostMapping("/locus")
    public AjaxResult selectCarLocus(@RequestBody String body){
        String deviceNo = JacksonUtil.parseString(body,"deviceNo");
        String endTime = JacksonUtil.parseString(body,"endTime");
        String startTime = JacksonUtil.parseString(body,"startTime");
        String pageNumber = JacksonUtil.parseString(body,"pageNumber");
        String pageSize = JacksonUtil.parseString(body,"pageSize");
        Map<String,Object> params = new HashMap<>();
        params.put("deviceNo",deviceNo);
        params.put("endTime",endTime);
        params.put("startTime",startTime);
        params.put("pageNumber",pageNumber);
        params.put("pageSize",pageSize);
        String url = "https://api.ly-gps.com/lygps-api/v2/locus/getDeviceLocus";
        AjaxResult ajaxResult = RequestUtil.post(url,params);

        assert ajaxResult != null;
        if (!ajaxResult.get("code").toString().equals("200")){
            return ajaxResult;
        }
        Object x;          //转换前经度
        Object y;          //转换前纬度
        double lot;        //转换后经度
        double lat;        //转换后纬度

        String data = ajaxResult.get("data").toString();
        Map<String, Object> dataMap = JSON.parseObject(data, new TypeReference<Map<String, Object>>() {});
        String dataList = dataMap.get("dataList").toString();
        List<Map<String,Object>> list = JSON.parseObject(dataList, new TypeReference<ArrayList<LinkedHashMap<String, Object>>>() {});
        long total = Long.parseLong(dataMap.get("total").toString());
        for (int i = 0; i <  list.size();){
            Map<String,Object> map = list.get(i);
            x = map.get("x");
            y = map.get("y");
            if (x != null && y != null && !x.equals("0") && !y.equals("0")) {
                lot = Double.parseDouble(x.toString());
                lat = Double.parseDouble(y.toString());
//                double[] loc = MapUtil.wgs2bd(lat,lot);
//                map.put("lot", loc[1]);
//                map.put("lat", loc[0]);
                double[] loc = CoordinateTransformUtil.gcj02tobd09(lot,lat);
                map.put("lot", Optional.of(loc[0]));
                map.put("lat", Optional.of(loc[1]));
                i ++;
            }else {
                list.remove(i);
            }
        }

        AjaxResult result = new AjaxResult();
        result.put("total", Optional.of(total));
        result.put("dataList",list);
        return result;
    }

    /**
     * 日常统计
     */
    @PreAuthorize("@ss.hasAnyRoles('admin, common')")
    @PostMapping("/dailyStatistic")
    public AjaxResult getDailyStatistic(@RequestBody String body){
//        String url = "https://api.ly-gps.com/lygps-api/v2/report/countDaily";
//        return CarUtil.statistic(url,body);
        return CarUtil.statistic(body);
    }

    /**
     * 月度统计
     */
    @PreAuthorize("@ss.hasAnyRoles('admin, common')")
    @PostMapping("/monthStatistic")
    public AjaxResult getMonthStatistic(@RequestBody String body){
//        String url = "https://api.ly-gps.com/lygps-api/v2/report/countMonth";
//        return CarUtil.statistic(url,body);
        return CarUtil.statistic(body);
    }

    /**
     * 行车统计
     */
    @PreAuthorize("@ss.hasAnyRoles('admin, common')")
    @PostMapping("/drivingStatistic")
    public AjaxResult getDrivingStatistic(@RequestBody String body){
        String url = "https://api.ly-gps.com/lygps-api/v2/report/countDriving";
        return CarUtil.statistic(url,body);
//        return CarUtil.statistic(body);
    }

    /**
     * 停车统计
     */
    @PreAuthorize("@ss.hasAnyRoles('admin, common')")
    @PostMapping("/parkingStatistic")
    public AjaxResult getParkingStatistic(@RequestBody String body){
        String url = "https://api.ly-gps.com//lygps-api/v2/report/countParking";
        return CarUtil.statistic(url,body);
//        return CarUtil.statistic(body);
    }

    /**
     *通过车牌号获取下拉框选项
     */
    @PreAuthorize("@ss.hasAnyRoles('admin, common')")
    @GetMapping("/selectitems")
    public AjaxResult getSelectItems(){
        long userId = SecurityUtils.getUserId();
        return AjaxResult.success(infoCarService.getSelectItemsByUserId(userId));
    }

    /**
     * 定时存储车辆日志
     */
    @Scheduled(fixedRate = 30000,initialDelay = 5000)
    public void autoRecordVehiclesLog() {
        System.out.println("开始获取设备信息");
        long countAll = infoCarService.selectCountAll();
        int finalPageSize = 20;
        long threadNum = countAll % finalPageSize == 0 ? countAll / finalPageSize : countAll / finalPageSize + 1;
        for (int i = 0; i < threadNum; i++) {
            long finalBegin = (long) i * finalPageSize;
            int finalI = i;
            threadPoolTaskExecutor.execute(() -> {
                System.out.println("线程"+ finalI +"开始执行");
                try {
                    CarUtil.writingLog(finalBegin,finalPageSize);
                }catch (Exception e){
                    e.printStackTrace();
                }
                System.out.println("线程"+ finalI +"执行结束");
            });
        }
    }

    /**
     * 定时刷新令牌有效时间
    */
    @Scheduled(fixedRate = 18000000,initialDelay = 1000)
    public void refreshIdentityIdAndToken(){
        System.out.println("开始刷新令牌时间");
        String url = "https://api.ly-gps.com/lygps-api/v2/auth/refreshToken";
        Map<String,Object> params = new HashMap<>();
        params.put("loginName",RequestUtil.getLoginName());
        params.put("password",RequestUtil.getPassword());
        AjaxResult ajaxResult = RequestUtil.post(url,params);
        assert ajaxResult != null;
        String code = ajaxResult.get("code").toString();
        if (code.equals("701") || code.equals("400")){
            RequestUtil.getIdentityIdAndToken();
        }
        System.out.println("令牌时间已刷新");
    }

    @PreAuthorize("@ss.hasAnyRoles('admin,common')")
    @PostMapping("/countorder")
    public AjaxResult countOrder(@RequestBody VinfoCountOrderVo vinfoCountOrderVo){
        return AjaxResult.success(vinfoCountOrderService.selectList(vinfoCountOrderVo));
    }


    @PreAuthorize("@ss.hasPermi('info:car:export')")
    @Log(title = "月度统计", businessType = BusinessType.EXPORT)
    @PostMapping("/exportmonth")
    public void exportMonth(@RequestParam("startTime")Long start, @RequestParam("endTime") Long end,@RequestParam("pageNumber") Integer pageNumber,@RequestParam("pageSize") Integer pageSize,@RequestParam(name = "carNoList",required = false)String[] carNos, HttpServletResponse response)
    {
        Date startTime = new Date(start);
        Date endTime = new Date(end);
        List<String> carNoList = null;
        if (carNos != null)
            carNoList = Arrays.asList(carNos);
        List<VinfoCountMonth> list = vinfoCountOrderService.selectCountMonth(startTime,endTime,pageNumber,pageSize,carNoList);
        ExcelUtil<VinfoCountMonth> util = new ExcelUtil<>(VinfoCountMonth.class);
        util.exportExcel(response, list, "月度统计数据");
    }

    @PreAuthorize("@ss.hasPermi('info:car:export')")
    @Log(title = "日常统计", businessType = BusinessType.EXPORT)
    @PostMapping("/exportdaily")
    public void exportDaily(@RequestParam("beginTime")Long start, @RequestParam("endTime") Long end,@RequestParam("pageNumber") Integer pageNumber,@RequestParam("pageSize") Integer pageSize,@RequestParam(name = "carNoList",required = false)String[] carNos, HttpServletResponse response)
    {
        Date startTime = new Date(start);
        Date endTime = new Date(end);
        List<String> carNoList = null;
        if (carNos != null)
            carNoList = Arrays.asList(carNos);
        List<VinfoCountDaily> list = vinfoCountOrderService.selectCountDaily(startTime,endTime,pageNumber,pageSize,carNoList);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        list.forEach(vinfoCountOrder -> {
            vinfoCountOrder.setStartTime(simpleDateFormat.format(startTime));
        });
        ExcelUtil<VinfoCountDaily> util = new ExcelUtil<>(VinfoCountDaily.class);
        util.exportExcel(response, list, "日常统计数据");
    }

    @PreAuthorize("@ss.hasPermi('info:car:export')")
    @Log(title = "订单统计", businessType = BusinessType.EXPORT)
    @PostMapping("/exportorder")
    public void exportOrder(@RequestParam("startTime")Long startTime,
                            @RequestParam("endTime") Long endTime,
                            @RequestParam("pageNumber") Integer pageNumber,
                            @RequestParam("pageSize") Integer pageSize,
                            @RequestParam(name = "carNoList",required = false)String[] carNoList,
                            HttpServletResponse response){
        System.out.println("====="+startTime);
        VinfoCountOrderVo vinfoCountOrderVo = new VinfoCountOrderVo();
        vinfoCountOrderVo.setStartTime(new Date(startTime));
        vinfoCountOrderVo.setEndTime(new Date(endTime));
        vinfoCountOrderVo.setStart(Long.valueOf((long) (pageNumber - 1) * pageSize));
        vinfoCountOrderVo.setPageNumber(pageNumber);
        vinfoCountOrderVo.setPageSize(pageSize);
        if (carNoList != null)
                vinfoCountOrderVo.setCarNoList(Arrays.asList(carNoList));
        List<VinfoCountOrder> vinfoCountOrderList = vinfoCountOrderService.selectList(vinfoCountOrderVo).getList();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        vinfoCountOrderList.forEach(vinfoCountOrder -> {
            vinfoCountOrder.setStartTime(simpleDateFormat.format(startTime));
        });
        ExcelUtil<VinfoCountOrder> util = new ExcelUtil<>(VinfoCountOrder.class);
        util.exportExcel(response,vinfoCountOrderList,"订单统计数据");
    }

}
